package net.pinnoocle.playservice.service;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import net.pinnoocle.playcommon.constant.Constant;
import net.pinnoocle.playcommon.exception.ShopException;
import net.pinnoocle.playcommon.response.ErrorCode;
import net.pinnoocle.playcommon.utils.HelpUtils;
import net.pinnoocle.playcommon.utils.OssFileUtil;
import net.pinnoocle.playcommon.utils.UploadWxMedia;
import net.pinnoocle.playcommon.utils.WechatUtils;
import net.pinnoocle.playdao.entity.OssConfig;
import net.pinnoocle.playdao.entity.ShopWechatSetting;
import net.pinnoocle.playdao.entity.analysis.user.UserPercentVo;
import net.pinnoocle.playdao.entity.shopPc.homePage.DoubleVo;
import net.pinnoocle.playdao.entity.shopPc.homePage.NumberVo;
import net.pinnoocle.playservice.service.impl.OssConfigServiceImpl;
import net.pinnoocle.playservice.service.impl.ShopWechatSettingServiceImpl;
import net.pinnoocle.playservice.service.impl.UserServiceImpl;
import net.pinnoocle.playservice.service.impl.WxServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.MessageFormat;
import java.util.*;

/**
 * @author ye
 * @Description
 * @create 2021-10-28 14:29
 */
@Service("commonService")
@Slf4j
public class CommonService {

    @Value("${upload.folder}")
    private String uploadFolder;

    @Value("${upload.mapUrl}")
    private String uploadMapUrl;

    @Value("${upload.certPath}")
    private String certPath;

    @Autowired
    OssConfigServiceImpl ossConfigService;
    @Autowired
    ShopWechatSettingServiceImpl shopWechatSettingService;
    @Autowired
    UserServiceImpl userService;
    @Autowired
    WxServiceImpl wxService;

    /**
     * 上传图片
     * @param file
     * @return
     */
    public String uploadFile(MultipartFile file){
        String imageUrl = "";
        OssConfig ossConfig = ossConfigService.getOne(null);
        if(Objects.nonNull(ossConfig) && ossConfig.getIsOpen() == 1){
            imageUrl = uploadFileToOss(file, ossConfig);
        }else{
            imageUrl = uploadFileToLocal(file);
        }
        return imageUrl;
    }

    /**
     * 文件上传本地
     * @param file
     * @return
     */
    public String uploadFileToLocal(MultipartFile file){
        final List<String> contentTypes = Arrays.asList(".jpeg", ".jpg", ".png");
        if (file.isEmpty()) {
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"请上传图片");
        }
        String fileName = file.getOriginalFilename();
        if(Objects.isNull(fileName)){
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"文件资源获取失败");
        }
        String suffixName = fileName.substring(fileName.lastIndexOf("."));
        //校验文件类型
        if (!contentTypes.contains(suffixName)) {
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"请上传图片类型");
        }
        fileName = HelpUtils.getUUID() + suffixName; // 新文件名
        File dest = new File(uploadFolder + fileName);
        if (!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }
        try {
            file.transferTo(dest);
        } catch (IOException e) {
            return null;
        }
        return uploadMapUrl + fileName;
    }

    /**
     * 上传到微信
     * @param file
     * @return
     */
    public String uploadImageToWx(MultipartFile file){
        final List<String> contentTypes = Arrays.asList(".jpeg", ".jpg", ".png");
        if (file.isEmpty()) {
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"请上传图片");
        }
        String fileName = file.getOriginalFilename();
        if(Objects.isNull(fileName)){
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"文件资源获取失败");
        }
        String suffixName = fileName.substring(fileName.lastIndexOf("."));
        //校验文件类型
        if (!contentTypes.contains(suffixName)) {
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"请上传图片类型");
        }
        fileName = HelpUtils.getUUID() + suffixName; // 新文件名
        File dest = new File(uploadFolder + fileName);
        if (!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }
        try {
            file.transferTo(dest);
        } catch (IOException e) {
            log.info("上传失败："+e.getMessage());
            return null;
        }
        return uploadFolder + fileName;
    }

    /**
     * 上传图片至阿里云
     * @param file
     * @return
     */
    public String uploadFileToOss(MultipartFile file,OssConfig ossConfig){
        if(Objects.isNull(ossConfig)){
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"OSS配置未获取到，请联系管理员");
        }
        HashMap<String, String> ossMap = new HashMap<>();
        ossMap.put("endpoint",ossConfig.getEndpoint());
        ossMap.put("access_key",ossConfig.getAccessKey());
        ossMap.put("secret_key",ossConfig.getSecretKey());
        ossMap.put("bucket_name",ossConfig.getBucketName());
        String result = OssFileUtil.uploadPicture(file, "play/",ossMap);
        if(Objects.isNull(result)){
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"上传失败");
        }
        return result;
    }

    /**
     * 上传支付证书
     * @param file
     * @param shopId
     * @return
     */
    public String uploadCertFile(MultipartFile file,String shopId){
        if (file.isEmpty()) {
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"请上传证书文件");
        }
        String fileName = file.getOriginalFilename();
        if(Objects.isNull(fileName)){
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"文件资源获取失败");
        }
        String suffixName = fileName.substring(fileName.lastIndexOf("."));
        //校验文件类型
        if (!suffixName.equals(".p12")) {
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"请上传扩展名为p12的证书文件");
        }
        fileName = shopId + "_apiclientCert" + suffixName; // 新文件名
        File dest = new File(certPath+shopId+"/" + fileName);
        if (!dest.getParentFile().exists()) {
            dest.getParentFile().mkdirs();
        }
        try {
            file.transferTo(dest);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return fileName;
    }

    /**
     * 小程序二维码
     * @param scene
     * @param shopId
     * @param page
     * @return
     */
    public String getWxUnlimitedCode(String scene,String shopId,String page){
        //String accessToken = getAccessToken(shopId);
        String accessToken = wxService.getAuthorizerToken(shopId);//第三方平台access_token
        String getCodeUrl = MessageFormat.format(Constant.getWxUnlimitedCode,accessToken);
        String baseFileName = uploadFolder + "/qr/";
        File baseFile = new File(baseFileName);
        if(!baseFile.exists()){
            baseFile.mkdirs();
        }
        String fileName = scene.replace("&","_") + ".png";
        File file = new File(baseFileName + fileName);
        if(file.exists()){
            return uploadMapUrl + fileName;
        }
        try
        {
            URL url = new URL(getCodeUrl);
            HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
            httpURLConnection.setRequestMethod("POST");// 提交模式
            // 发送POST请求必须设置如下两行
            httpURLConnection.setDoOutput(true);
            httpURLConnection.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            PrintWriter printWriter = new PrintWriter(httpURLConnection.getOutputStream());
            // 发送请求参数
            JSONObject paramJson = new JSONObject();
            paramJson.put("scene", scene);
            paramJson.put("width", 430);
            paramJson.put("auto_color", true);
            paramJson.put("env_version","trial");
            if(StringUtils.isNotBlank(page)){
                paramJson.put("page", page);
            }
            printWriter.write(paramJson.toString());
            // flush输出流的缓冲
            printWriter.flush();
            //开始获取数据
            BufferedInputStream bis = new BufferedInputStream(httpURLConnection.getInputStream());
            OutputStream os = new FileOutputStream(baseFileName + fileName);
            int len;
            byte[] arr = new byte[1024];
            while ((len = bis.read(arr)) != -1)
            {
                os.write(arr, 0, len);
                os.flush();
            }
            os.close();
        }
        catch (Exception e)
        {
            log.info("二维码获取失败:"+e.getMessage());
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR,"二维码获取失败");
        }
        return uploadMapUrl + fileName;
    }

    /**
     * 获取微信accessToken
     * @param shopId
     * @return
     */
    public String getAccessToken(String shopId) {
        String access_token = "";
        ShopWechatSetting wechatSetting = shopWechatSettingService.getOne(new QueryWrapper<ShopWechatSetting>()
                .lambda()
                .eq(ShopWechatSetting::getShopId, shopId)
                .last("LIMIT 1"));
        if (Objects.isNull(wechatSetting)) {
            throw new ShopException(ErrorCode.PARAMS_GET_ERROR, "小程序未知设置");
        }
        if (StringUtils.isNotBlank(wechatSetting.getAccessToken()) &&
                !HelpUtils.compareDateToNow(wechatSetting.getExpireTime())) {
            access_token = wechatSetting.getAccessToken();
        } else {
            String appId = wechatSetting.getAppId();
            String secret = wechatSetting.getAppSecret();
            JSONObject wechatAccessTokenJson = WechatUtils.getWechatAccessToken(appId, secret);
            if (wechatAccessTokenJson.containsKey("errcode") && wechatAccessTokenJson.getInteger("errcode") > 0) {
                log.info("获取微信token失败===" + wechatAccessTokenJson.containsKey("errcode"));
                throw new ShopException(ErrorCode.PARAMS_GET_ERROR, "获取微信AccessToken失败");
            }
            access_token = wechatAccessTokenJson.getString("access_token");
            Integer expiresIn = wechatAccessTokenJson.getInteger("expires_in");
            Date newDate = DateUtil.offset(new Date(), DateField.SECOND, expiresIn);
            wechatSetting.setAccessToken(access_token);
            wechatSetting.setExpireTime(newDate);
            shopWechatSettingService.updateById(wechatSetting);
        }
        return access_token;
    }

    /**
     * 获取统计趋势
     * @param todayNum
     * @param yesterdayNum
     * @return
     */
    public NumberVo getNumberVo(Integer todayNum,Integer yesterdayNum){
        NumberVo numberVo = new NumberVo();
        HashMap<String, Object> userTrend = HelpUtils.getNumberTrendValue(todayNum, yesterdayNum);
        numberVo.setTodayNum(todayNum);
        numberVo.setYesterdayNum(yesterdayNum);
        numberVo.setTrendType((Integer) userTrend.get("trendType"));
        numberVo.setTrendValue((String) userTrend.get("trendValue"));
        return numberVo;
    }

    /**
     * 获取统计趋势
     * @param todayNum
     * @param yesterdayNum
     * @return
     */
    public DoubleVo getDoubleVo(Double todayNum,Double yesterdayNum){
        DoubleVo doubleVo = new DoubleVo();
        HashMap<String, Object> trendValue = HelpUtils.getNumberTrendValue(todayNum, yesterdayNum);
        doubleVo.setTodayNum(todayNum);
        doubleVo.setYesterdayNum(yesterdayNum);
        doubleVo.setTrendType((Integer) trendValue.get("trendType"));
        doubleVo.setTrendValue((String) trendValue.get("trendValue"));
        return doubleVo;
    }
}
